#pragma once
#include <vector>
#include <string>
#include <jsoncpp/json/json.h>
#include <queue>
#include <set>
class wuzi
{
public:
#define CHESS_WHITE 1
#define CHESS_BLACK 2
    void check_win(Json::Value const &request, Json::Value &response) // row,col代表当前下棋的位置
    {
        // need params: board_info, board_info[white], board_info[black], row, col, color, white_id, black_id
        if (request["board_info"].empty())
        {
            response["result"] = false;
            response["reason"] = "no params: board_info";
            return;
        }
        if (request["white_id"].empty() || request["black_id"].empty())
        {
            response["result"] = false;
            response["reason"] = "no params: white_id or black_id";
            return;
        }
        if (request["row"].empty() || request["col"].empty())
        {
            response["result"] = false;
            response["reason"] = "no params: row or col";
            return;
        }
        if (request["color"].empty())
        {
            response["result"] = false;
            response["reason"] = "no params: color";
            return;
        }
        init_board(request["board_info"]);
	    response["winner_id"] = 0;
        // 从下棋位置的四个不同方向上检测是否出现了5个及以上相同颜色的棋子（横行，纵列，正斜，反斜）
        if (five(request["row"].asInt(), request["col"].asInt(), 0, 1, request["color"].asInt()) ||
            five(request["row"].asInt(), request["col"].asInt(), 1, 0, request["color"].asInt()) ||
            five(request["row"].asInt(), request["col"].asInt(), -1, 1, request["color"].asInt()) ||
            five(request["row"].asInt(), request["col"].asInt(), -1, -1, request["color"].asInt()))
        {
            // 任意一个方向上出现了true也就是胜利，设置返回值
            response["result"] = true;
            response["winner_id"] = request["color"].asInt() == CHESS_WHITE ? request["white_id"] : request["black_id"];
            return;
        }
        response["result"] = true;
        return;
    }
    // AI函数：返回最佳落子位置
    void ai_gobang(Json::Value const &request, Json::Value &response)
    {
        // need params: board_info, board_info[white], board_info[black], color
        if (request["board_info"].empty())
        {
            response["result"] = false;
            response["reason"] = "no params: board_info";
            return;
        }
        init_board(request["board_info"]);
        int color = request["color"].asInt();
        int bestScore = INT32_MIN;
        std::vector<std::pair<int, int>> bestMoves;

        // 仅扫描已有棋子周围3格内的空位
        for (int i = 0; i < 15; ++i)
        {
            for (int j = 0; j < 15; ++j)
            {
                if (_board[i][j] != 0)
                    continue; // 跳过非空位

                // 检查是否邻近已有棋子
                bool hasNeighbor = false;
                for (int di = -3; di <= 3; ++di)
                {
                    for (int dj = -3; dj <= 3; ++dj)
                    {
                        int ni = i + di, nj = j + dj;
                        if (ni >= 0 && ni < 15 && nj >= 0 && nj < 15 && _board[ni][nj] != 0)
                        {
                            hasNeighbor = true;
                            break;
                        }
                    }
                    if (hasNeighbor)
                        break;
                }
                if (!hasNeighbor)
                    continue;

                // 计算进攻分（己方棋型）
                int attackScore = 0;
                for (const auto &dir : DIRS)
                {
                    attackScore += evaluateDirection(i, j, color, dir[0], dir[1], _board);
                }

                // 计算防守分（对手棋型）
                int opponentColor = (color == 1) ? 2 : 1;
                int defenseScore = 0;
                for (const auto &dir : DIRS)
                {
                    defenseScore += evaluateDirection(i, j, opponentColor, dir[0], dir[1], _board);
                }

                // 总分 = 进攻分 * 1.2 + 防守分 * 1.0（进攻略优先）
                int totalScore = attackScore * 1.2 + defenseScore;

                // 更新最佳落子点
                if (totalScore > bestScore)
                {
                    bestScore = totalScore;
                    bestMoves.clear();
                    bestMoves.push_back({i, j});
                }
                else if (totalScore == bestScore)
                {
                    bestMoves.push_back({i, j});
                }
            }
        }

        // 若无合适位置（开局第一步），落子中心
        if (bestMoves.empty())
        {
            response["result"] = true;
            response["pos"].append(7);
            response["pos"].append(7);
            return;
        }

        // 随机选择一个最高分位置
        srand(time(0));
        auto pos = bestMoves[rand() % bestMoves.size()];
        response["result"] = true;
        response["pos"].append(pos.first);
        response["pos"].append(pos.second);
        return;
    }

private:
    bool init_board(Json::Value const &board_info)
    {
        _board = std::vector<std::vector<int>>(15, std::vector<int>(15, 0));
        for (const auto &e : board_info["black"])
        { 
            if (!e.isString())
            {
                continue; // 跳过非字符串元素
            }
            std::string str = e.asString();
            std::istringstream ss(str);
            int x, y;
            char comma; // 用于捕获逗号分隔符
            if (ss >> x >> comma >> y)
            {
                _board[x][y] = CHESS_BLACK;      
            }
        }
        for (const auto &e : board_info["white"])
        {
            if (!e.isString())
            {
                continue; // 跳过非字符串元素
            }
            std::string str = e.asString();
            std::istringstream ss(str);
            int x, y;
            char comma; // 用于捕获逗号分隔符
            if (ss >> x >> comma >> y)
            {
                _board[x][y] = CHESS_WHITE;
            }
        }
        return true;
    }
    bool five(int row, int col, int row_off, int col_off, int color)
    {
        int count = 1;
        int search_row = row + row_off;
        int search_col = col + col_off;
        while (search_row >= 0 && search_row < 15 &&
               search_col >= 0 && search_col < 15 &&
               _board[search_row][search_col] == color)
        {
            // 同色棋子数量++
            count++;
            // 检索位置继续向后偏移
            search_row += row_off;
            search_col += col_off;
        }
        // 从相反方向继续
        search_row = row - row_off;
        search_col = col - col_off;
        while (search_row >= 0 && search_row < 15 &&
               search_col >= 0 && search_col < 15 &&
               _board[search_row][search_col] == color)
        {
            // 同色棋子数量++
            count++;
            // 检索位置继续向后偏移
            search_row -= row_off;
            search_col -= col_off;
        }
        return (count >= 5);
    }
    // 五子棋人机落子函数

    // 预定义棋型分值（进攻与防守共用）
    const int SCORE_TABLE[11] = {
        0,      // 无效棋型（如混杂敌我棋子）
        1,      // 单子
        10,     // 眠二（一端被堵）
        50,     // 活二
        100,    // 眠三
        1000,   // 活三
        500,    // 冲四（一端被堵）
        10000,  // 活四
        500000, // 冲五（已赢，但保留逻辑）
        1000000 // 连五（胜利）
    };

    // 计算某位置在指定方向的棋型得分
    int evaluateDirection(int row, int col, int color, int dx, int dy, std::vector<std::vector<int>> &_board)
    {
        int score = 0;
        int consecutive = 0;       // 连续同色棋子数
        int openEnds = 0;          // 开放端数量（两端为空）
        bool blockedLeft = false;  // 左侧是否被堵
        bool blockedRight = false; // 右侧是否被堵

        // 向左扫描
        int r = row - dx, c = col - dy;
        while (r >= 0 && r < 15 && c >= 0 && c < 15)
        {
            if (_board[r][c] == color)
                consecutive++;
            else if (_board[r][c] == 0)
            {
                openEnds++;
                break;
            }
            else
            {
                blockedLeft = true;
                break;
            }
            r -= dx;
            c -= dy;
        }

        // 向右扫描
        r = row + dx;
        c = col + dy;
        while (r >= 0 && r < 15 && c >= 0 && c < 15)
        {
            if (_board[r][c] == color)
                consecutive++;
            else if (_board[r][c] == 0)
            {
                openEnds++;
                break;
            }
            else
            {
                blockedRight = true;
                break;
            }
            r += dx;
            c += dy;
        }

        // 根据连续数和开放端确定棋型
        if (consecutive >= 4)
            return SCORE_TABLE[9]; // 连五
        if (consecutive == 3)
        {
            if (openEnds == 2)
                return SCORE_TABLE[5]; // 活三
            if (openEnds == 1)
                return SCORE_TABLE[4]; // 眠三
        }
        if (consecutive == 2)
        {
            if (openEnds == 2)
                return SCORE_TABLE[3]; // 活二
            if (openEnds == 1)
                return SCORE_TABLE[2]; // 眠二
        }
        if (consecutive == 1 && openEnds >= 1)
            return SCORE_TABLE[1]; // 单子
        return 0;
    }

private:
    std::vector<std::vector<int>> _board = std::vector<std::vector<int>>(15, std::vector<int>(15, 0));
    // 方向数组：水平、垂直、正斜、反斜
    const int DIRS[4][2] = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
};
